package go_pool

// Job 定义协程任务的接口
type Job interface {
	Do() error
}

// Worker 定义Worker结构体，用来执行协程任务
type Worker struct {
	jobQueue chan Job      // 协程任务队列
	stop     chan struct{} // 任务是否停止
}

func newWorker() *Worker {
	//无缓冲chan，一个worker只能运行一个协程任务
	return &Worker{
		jobQueue: make(chan Job),
		stop:     make(chan struct{}),
	}
}

// Run Worker执行协程任务，并且worker进入chan，onPanic是发生恐慌时的回调方法
func (w *Worker) run(wq chan<- *Worker, onPanic func(data interface{})) {
	go func() {
		defer func() {
			// panic会终止协程，导致workerNum-1，所以需要重新Run开启一个协程替换掉这个panic的协程
			if r := recover(); r != nil {
				w.run(wq, onPanic)
				wq <- w
				if onPanic != nil {
					onPanic(r)
				}
			}
		}()

		for {
			select {
			case job := <-w.jobQueue:
				// 开始执行任务
				job.Do()
				// 任务执行完后worker入队等待下一次协程任务
				wq <- w
			case <-w.stop:
				// 协程任务终止
				return
			}
		}
	}()
}

// Close worker chan关闭，即回收worker
func (w *Worker) close() {
	w.stop <- struct{}{}
	close(w.stop)
	close(w.jobQueue)
}

// 停止运行
func (w Worker) stopRun() {
	w.stop <- struct{}{}
}
